/* 
 *  Syntelos XB
 *  Copyright (C) 2006 John Pritchard.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307 USA
 */

package syntelos.xb;

/**
 * <p> Specific to CF (Java Class File) format. </p>
 * 
 * @see XB
 * @see Base
 * 
 * @author John Pritchard (jdp@syntelos.com)
 */
public interface CF 
    extends IO
{

    public interface Reader 
        extends java.io.DataInput
    {
        public class Stream
            extends java.io.DataInputStream
            implements CF.Reader
        {
            public Stream(java.io.InputStream in){
                super(in);
            }
        }
    }

    public interface Writer
        extends java.io.DataOutput
    {
        public class Stream
            extends java.io.DataOutputStream
            implements CF.Writer
        {
            public Stream(java.io.OutputStream out){
                super(out);
            }
        }
        public class Buffer
            extends syntelos.iou.bbod
            implements CF.Writer
        {
            public Buffer(){
                super();
            }
            public Buffer(syntelos.iou.bbuf buf){
                super(buf);
            }
        }
    }


    /** 
     * <p> The class file constant pool maintains array order, and unique
     * component identity. </p>
     * 
     */
    public final class Constants
        extends syntelos.iou.objmap
    {
        /**
         * Tag zero is undefined for the JCF constant pool, used
         * internally for a special "null tag".
         * 
         * @see CF$Constants$Const#NIL
         */
        public final static byte NIL           =  0;
        /**
         * Tag one is defined for the JCF constant pool.
         */
        public final static byte UTF8          =  1;
        public final static byte INTEGER       =  3;
        public final static byte FLOAT         =  4;
        public final static byte LONG          =  5;
        public final static byte DOUBLE        =  6;
        public final static byte CLASS         =  7;
        public final static byte STRING        =  8;
        public final static byte FIELDREF      =  9;
        public final static byte METHODREF     = 10;
        public final static byte IMETHODREF    = 11;
        public final static byte NAME_AND_TYPE = 12;

        public final static java.lang.String SCHEME_NIL           = "const";
        public final static java.lang.String SCHEME_UTF8          = "utf8";
        public final static java.lang.String SCHEME_INTEGER       = "int";
        public final static java.lang.String SCHEME_FLOAT         = "float";
        public final static java.lang.String SCHEME_LONG          = "long";
        public final static java.lang.String SCHEME_DOUBLE        = "double";
        public final static java.lang.String SCHEME_CLASS         = "class";
        public final static java.lang.String SCHEME_STRING        = "string";
        public final static java.lang.String SCHEME_FIELDREF      = "field";
        public final static java.lang.String SCHEME_METHODREF     = "method";
        public final static java.lang.String SCHEME_IMETHODREF    = "interface-method";

        private final static syntelos.iou.objmap dict = new syntelos.iou.objmap();
        static {
            dict.put(SCHEME_NIL,new java.lang.Integer(NIL));
            dict.put(SCHEME_UTF8,new java.lang.Integer(UTF8));
            dict.put(SCHEME_INTEGER,new java.lang.Integer(INTEGER));
            dict.put(SCHEME_FLOAT,new java.lang.Integer(FLOAT));
            dict.put(SCHEME_LONG,new java.lang.Integer(LONG));
            dict.put(SCHEME_DOUBLE,new java.lang.Integer(DOUBLE));
            dict.put(SCHEME_CLASS,new java.lang.Integer(CLASS));
            dict.put(SCHEME_STRING,new java.lang.Integer(STRING));
            dict.put(SCHEME_FIELDREF,new java.lang.Integer(FIELDREF));
            dict.put(SCHEME_METHODREF,new java.lang.Integer(METHODREF));
            dict.put(SCHEME_IMETHODREF,new java.lang.Integer(IMETHODREF));
        }
        /**
         * <p> Categorize known URI scheme for fast processsing. </p>
         * 
         * @param scheme Reference URI scheme subcomponent
         * @return Constant value for recognized schemes, e.g., {@link
         * syntelos.xb.CF$Constants#SCHEME_UTF8}
         */
        public final static int Scheme(java.lang.String scheme){
            java.lang.Integer re = (java.lang.Integer)dict.get(scheme);
            if (null != re)
                return re.intValue();
            else
                return NIL;
        }
        /**
         * <p> Categorize known URI scheme for fast processsing. </p>
         * 
         * @param uri Reference URI 
         * @return Constant value for scheme head subcomponent, e.g.,
         * {@link syntelos.xb.CF$Constants#SCHEME_UTF8}
         */
        public final static int Scheme(IO.Uri uri){
            return Scheme(uri.getSchemeHead());
        }

        
        /**
         * <p> An entry in the constant pool is looked- up by its CP
         * index (counting from one), or Key.  </p>
         * 
         * <h3>Keyed identity</h3>
         * 
         * <p> Each {@link syntelos.xb.CF$Constants$Const}
         * subclass has a specialized Key object class for both normal
         * (known value) and forward (unknown value) reference.  The
         * {@link syntelos.xb.CF$Constants} interface (API)
         * handles the key protocol for each {@link
         * syntelos.xb.CF$Constants$Const} subclass.  The lookup
         * identity is used to ensure that each constant pool entry is
         * unique within the JCF constant pool.  </p>
         */
        public abstract static class Const
            extends java.lang.Object
        {
        
            /**
             * <p> The "null const" has tag value zero (undefined) and
             * reads and writes nothing.  Its key is the empty string.
             * A "valid" constant pool has an instance of this class
             * at index zero.  This validity is maintained by the
             * package for all use cases --- an empty pool writes
             * nothing, and a non empty pool will have a NIL entry at
             * index zero. </p>
             * 
             * @see CF$Constants$Const#NIL
             * @see CF$Constants#NIL
             * @see CF$Constants#add(syntelos.xb.CF$Constants$Const)
             */
            public final static class Nil 
                extends Const
            {
                Nil(){
                    super();
                }
        	
                public final int getTag(){
                    return 0;
                }
                public void writeXB (XB.Writer strbuf){}
                public void writeCF(CF.Writer str)
                    throws java.io.IOException
                {}
                public java.lang.String toString(){

                    return "const:nil";
                }
            }
            /**
             * <p> The "null const" is used as a placeholder following
             * long and double constants, and in slot zero of the
             * constant pool to consume index zero. </p>
             * 
             * @see CF$Constants$Const$Nil
             * @see CF$Constants#NIL
             */
            public final static Const NIL = new Nil();
        

            /** 
             * This entry's index in the constant pool. (type u2)
             */
            private int index;
        
            private final java.lang.Object key;
        
            /**
             * <p> Special CP ctor preprocessing only. </p>
             * @see CF.Constants$ReadcfTodo
             */
            protected Const(){
                super();
                this.key = "";
            }
        
            public Const (java.lang.Object key){
                super();
                if (null == key)
                    throw new Error.Argument("Missing key");
                else
                    this.key = key;
            }
        
            public abstract int getTag();
        
            public void writeCF(CF.Writer str)
                throws java.io.IOException
            {
            }
            public final java.lang.Object getKey(){
                return this.key;
            }
            /**
             * @return The positive index (counting from one) of this entry in
             * the {@link CF.Constants}
             * @see CF.Constants#getConst(int)
             */
            public final int getIndex(){
                return this.index; 
            }
            /**
             * @param index The positive (counting from one), 16bit position
             * of this entry in the {@link CF.Constants}
             * @see CF.Constants#getConst(int)
             */
            protected final void setIndex(int index){
                this.index = index;
            }
            public final int hashCode(){
                return this.key.hashCode();
            }
            public final boolean equals(java.lang.Object another){
                if (another == this)
                    return true;
                else if (another instanceof Const){
                    Const another_ent = (Const)another;
                    java.lang.Object another_key = another_ent.getKey();
                    java.lang.Object this_key = this.getKey();
                    if (another_key == this_key)
                        return true;
                    else
                        return this_key.equals(another_key);
                }
                else if (another == this.key)
                    return true;
                else
                    return this.key.equals(another);
            }
        
        }
        
        /** 
         * <p> A Class entry in the constant pool. </p>
         * 
         */
        public final static class Class 
            extends CF.Constants.Const 
        {
            public final static class Key
                extends java.lang.Object
            {
                private final java.lang.String string;
                private final int hashcode;
        
                public Key(CF.Constants.Utf8 string){
                    this(string.getString());
                }
                public Key(java.lang.String string){
                    super();
                    if (null == string)
                        throw new Error.Bug("missing-key-string");
                    else {
                        this.string = string;
                        this.hashcode = string.hashCode() ^ 0xF0F;
                    }
                }
                public int hashCode(){
                    return this.hashcode;
                }
                public boolean equals(java.lang.Object another){
                    if (another == this)
                        return true;
                    else if (another == this.string)
                        return true;
                    else
                        return this.string.equals(another.toString());
                }
                public java.lang.String toString(){
                    return this.string;
                }
            }
        
            private CF.Constants.Utf8 name;
        
            protected Class (CF.Constants.Utf8 n){
                this (new Key(n), n);
            }
            protected Class (Key key, CF.Constants.Utf8 n){
                super (key);
                this.name = n;
            }
        
            public int getTag() { 
                return CF.Constants.CLASS; 
            }
            public final CF.Constants.Utf8 getName(){
                return this.name;
            }
            public final java.lang.String getNameString(){
                return this.name.getString();
            }
            public void writeCF (CF.Writer dstr) 
                throws java.io.IOException
            {
                dstr.writeByte (CF.Constants.CLASS);
                dstr.writeShort (this.name.getIndex());
            }
            public java.lang.String toString(){
                syntelos.iou.chbuf strbuf = new syntelos.iou.chbuf();
                strbuf.append(SCHEME_CLASS);
                strbuf.append(':');
                strbuf.append(this.name.toString());
                return strbuf.toString();
            }
        }
        
        /**
         * <p> A NameAndType entry in the constant pool.  </p>
         * 
         */
        public final static class NameAndType 
            extends CF.Constants.Const
        {
            public final static class Key
                extends java.lang.Object
            {
                private final java.lang.String string;
                private final int hashcode;
        
                public Key (CF.Constants.Utf8 n, CF.Constants.Utf8 t){
                    this (n.getString(),t.getString());
                }
                public Key(java.lang.String n, java.lang.String t){
                    super();
                    if (null == n)
                        throw new Error.Bug("missing-name");
                    else if (null == t)
                        throw new Error.Bug("missing-type");
                    else {
                        this.string = syntelos.iou.chbuf.cat(n,"+",t).intern();
                        this.hashcode = this.string.hashCode();
                    }
                }
                public int hashCode(){
                    return this.hashcode;
                }
                public boolean equals(java.lang.Object another){
                    if (another == this)
                        return true;
                    else if (another == this.string)
                        return true;
                    else
                        return this.string.equals(another.toString());
                }
                public java.lang.String toString(){
                    return this.string;
                }
            }
        
            private CF.Constants.Utf8 name;
        
            private CF.Constants.Utf8 type;
        
            protected NameAndType (CF.Constants.Utf8 n, CF.Constants.Utf8 t){ 
                this (new Key(n,t),n,t);
            }
            protected NameAndType (Key key, CF.Constants.Utf8 n, CF.Constants.Utf8 t){ 
                super (key);
                this.name = n;
                this.type = t;
            }
        
            public int getTag() { 
                return CF.Constants.NAME_AND_TYPE; 
            }
            public final CF.Constants.Utf8 getName(){
                return this.name;
            }
            public final CF.Constants.Utf8 getType(){
                return this.type;
            }
            public void writeCF (CF.Writer dstr) 
                throws java.io.IOException
            {
                dstr.writeByte (CF.Constants.NAME_AND_TYPE);
                dstr.writeShort (this.name.getIndex());
                dstr.writeShort (this.type.getIndex());
            }
            public java.lang.String toString(){
                syntelos.iou.chbuf strbuf = new syntelos.iou.chbuf();
                strbuf.append("?name=");
                strbuf.append(IO.Uri.encode(this.name.toString()));
                strbuf.append("?type=");
                strbuf.append(IO.Uri.encode(this.type.toString()));
                return strbuf.toString();
            }
        }
        
        /**
         * @see FieldRef
         * @see MethodRef
         * @see IMethodRef
         * 
         */
        public static abstract class Ref 
            extends CF.Constants.Const
        {
            public final static class Key
                extends java.lang.Object
            {
                private final java.lang.String string;
                private final int hashcode;
        
                public Key (CF.Constants.Class c, CF.Constants.NameAndType nt){
                    this (c.getNameString(),nt.getKey().toString());
                }
                public Key(java.lang.String c, java.lang.String nt){
                    super();
                    if (null == c)
                        throw new Error.Bug("missing-class");
                    else if (null == nt)
                        throw new Error.Bug("missing-nameandtype");
                    else {
                        this.string = syntelos.iou.chbuf.cat(c.toString(),"+",nt.toString()).intern();
                        this.hashcode = this.string.hashCode();
                    }
                }
                public int hashCode(){
                    return this.hashcode;
                }
                public boolean equals(java.lang.Object another){
                    if (another == this)
                        return true;
                    else if (another == this.string)
                        return true;
                    else
                        return this.string.equals(another.toString());
                }
                public java.lang.String toString(){
                    return this.string;
                }
            }
        
            private CF.Constants.Class clas;
        
            private CF.Constants.NameAndType nameAndType;

            private int tag;
        
            protected Ref (int tag, CF.Constants.Class clas, CF.Constants.NameAndType nt){
                this (new Key(clas,nt), tag, clas, nt);
            }
            protected Ref (Key key, int tag, CF.Constants.Class clas, CF.Constants.NameAndType nameAndType){
                super (key);
                this.tag = tag;
                this.clas = clas;
                this.nameAndType = nameAndType;
            }
        
            public int getTag() { 
                return this.tag; 
            }
            public final CF.Constants.Class getRefClass(){
                return this.clas;
            }
            public final CF.Constants.NameAndType getNameAndType(){
                return this.nameAndType;
            }
        
            public void writeCF (CF.Writer dstr) 
                throws java.io.IOException
            {
                dstr.writeByte (this.tag);
                dstr.writeShort (this.clas.getIndex());
                dstr.writeShort (this.nameAndType.getIndex());
            }
            public java.lang.String toString(){
                syntelos.iou.chbuf strbuf = new syntelos.iou.chbuf();
                switch (tag){
                case FIELDREF:
                    strbuf.append(SCHEME_FIELDREF);
                    break;
                case METHODREF:
                    strbuf.append(SCHEME_METHODREF);
                    break;
                case IMETHODREF:
                    strbuf.append(SCHEME_IMETHODREF);
                    break;
                default:
                    throw new Error.Bug();
                }
                strbuf.append(':');
                strbuf.append(this.clas.toString());
                strbuf.append(this.nameAndType.toString());
                return strbuf.toString();
            }
        }
        /**
         * 
         * 
         */
        public final static class FieldRef 
            extends CF.Constants.Ref
        {
        
            protected FieldRef (CF.Constants.Class clas, CF.Constants.NameAndType nt){
                super (new Key(clas,nt), CF.Constants.FIELDREF, clas, nt);
            }
            public FieldRef (Key key, CF.Constants.Class clas, CF.Constants.NameAndType nameAndType){
                super (key,CF.Constants.FIELDREF,clas,nameAndType);
            }
        }
        /**
         * 
         * 
         */
        public final static class MethodRef 
            extends CF.Constants.Ref
        {        
            protected MethodRef (CF.Constants.Class clas, CF.Constants.NameAndType nt){
                super (new Key(clas,nt), CF.Constants.METHODREF, clas, nt);
            }
            public MethodRef (Key key, CF.Constants.Class clas, CF.Constants.NameAndType nameAndType){
                super (key,CF.Constants.METHODREF,clas,nameAndType);
            }
        }
        /**
         * 
         * 
         */
        public final static class IMethodRef 
            extends CF.Constants.Ref
        {        
            protected IMethodRef (CF.Constants.Class clas, CF.Constants.NameAndType nt){
                super (new Key(clas,nt), CF.Constants.IMETHODREF, clas, nt);
            }
            public IMethodRef (Key key, CF.Constants.Class clas, CF.Constants.NameAndType nameAndType){
                super (key,CF.Constants.IMETHODREF,clas,nameAndType);
            }
        }
        /**
         * 
         * 
         */
        public final static class String 
            extends CF.Constants.Const
        {
            public final static class Key
                extends java.lang.Object
            {
                private final java.lang.String string;
                private final int hashcode;
        
                public Key(CF.Constants.Utf8 string){
                    this(string.getString());
                }
                public Key(java.lang.String string){
                    super();
                    if (null == string)
                        throw new Error.Bug("missing-string");
                    else {
                        this.string = string.intern();
                        this.hashcode = string.hashCode() ^ 0xF30F;
                    }
                }
                public int hashCode(){
                    return this.hashcode;
                }
                public boolean equals(java.lang.Object another){
                    if (another == this)
                        return true;
                    else if (another == this.string)
                        return true;
                    else
                        return this.string.equals(another.toString());
                }
                public java.lang.String toString(){
                    return this.string;
                }
            }
        
            private CF.Constants.Utf8 str;
        
            protected String (CF.Constants.Utf8 str){
                this (new Key(str), str);
            }
            protected String (Key key, CF.Constants.Utf8 str){
                super (key);
                this.str = str;
            }
        
            public int getTag() { 
                return CF.Constants.STRING; 
            }
            public final CF.Constants.Utf8 getString(){
                return str;
            }
            public void writeCF (CF.Writer dstr) 
                throws java.io.IOException
            {
                dstr.writeByte (CF.Constants.STRING);
                dstr.writeShort (str.getIndex());
            }
            public java.lang.String toString(){
                syntelos.iou.chbuf strbuf = new syntelos.iou.chbuf();
                strbuf.append(SCHEME_STRING);
                strbuf.append(':');
                strbuf.append(this.str.toString());
                return strbuf.toString();
            }
        }
        /**
         * 
         * 
         */
        public final static class Utf8 
            extends CF.Constants.Const
        {
            public final static class Key
                extends java.lang.Object
            {
                private final java.lang.String string;
                private final int hashcode;
        
                public Key(java.lang.String string){
                    super();
                    if (null == string)
                        throw new Error.Bug("missing-string");
                    else {
                        this.string = string.intern();
                        this.hashcode = string.hashCode();
                    }
                }
                public int hashCode(){
                    return this.hashcode;
                }
                public boolean equals(java.lang.Object another){
                    if (another == this)
                        return true;
                    else if (another == this.string)
                        return true;
                    else
                        return this.string.equals(another.toString());
                }
                public java.lang.String toString(){
                    return this.string;
                }
            }
        
            private java.lang.String string;
        
            protected Utf8 (java.lang.String s){
                this (new Key(s),s);
            }
            protected Utf8 (Key key, java.lang.String s){
                super (key);
                this.string = this.getKey().toString();//(interned)
            }
        
            public int getTag() { 
                return CF.Constants.UTF8;
            }
            public final java.lang.String getString(){
                return this.string;
            }
            public void writeCF (CF.Writer dstr) 
                throws java.io.IOException
            {
                dstr.writeByte(CF.Constants.UTF8);
                dstr.writeUTF(this.string);
            }
            public java.lang.String toString(){
                syntelos.iou.chbuf strbuf = new syntelos.iou.chbuf();
                strbuf.append(SCHEME_UTF8);
                strbuf.append(':');
                strbuf.append(IO.Uri.encode(this.string));
                return strbuf.toString();
            }
        }
        /**
         * @see CF$Constants$Integer
         * @see CF$Constants$Float
         */
        public static abstract class Value1 
            extends CF.Constants.Const
        {
            public final static class Key
                extends java.lang.Object
            {
                private final int value;
                private final java.lang.String string;
                private final int hashcode;
        
                public Key(int value){
                    super();
                    this.value = value;
                    this.string = java.lang.Integer.toHexString(value);
                    this.hashcode = value;
                }
                public int hashCode(){
                    return this.hashcode;
                }
                public boolean equals(java.lang.Object another){
                    if (another == this)
                        return true;
                    else if (another instanceof java.lang.Number)
                        return (this.value == ((java.lang.Number)another).intValue());
                    else if (another == this.string)
                        return true;
                    else
                        return this.string.equals(another.toString());
                }
                public java.lang.String toString(){
                    return this.string;
                }
            }
        
            private int tag;
        
            private int value;
        
            protected Value1 (int tag, int value){
                this(new Key(value),tag,value);
            }
            protected Value1 (Key key, int tag, int value){
                super(key);
                this.tag = tag;
                this.value = value;
            }
        
            public int getTag() { 
                return this.tag; 
            }
            public final java.lang.Number getValue(){
                switch (this.tag){
                case CF.Constants.INTEGER:
                    return new java.lang.Integer(this.value);
                case CF.Constants.FLOAT:
                    float value = java.lang.Float.intBitsToFloat(this.value);
                    return new java.lang.Float(value);
                default:
                    throw new Error.Bug();
                }
            }
            public void writeCF (CF.Writer dstr) 
                throws java.io.IOException
            {
                dstr.writeByte (this.tag);
                dstr.writeInt (this.value);
            }
            public java.lang.String toString(){
                syntelos.iou.chbuf strbuf = new syntelos.iou.chbuf();
                switch(this.tag){
                case CF.Constants.INTEGER:
                    strbuf.append(SCHEME_INTEGER);
                    break;
                case CF.Constants.FLOAT:
                    strbuf.append(SCHEME_FLOAT);
                    break;
                default:
                    throw new Error.Bug("Unrecognized tag 0x"+java.lang.Integer.toHexString(this.tag));
                }
                strbuf.append(':');
                strbuf.append(this.getValue().toString());
                return strbuf.toString();
            }
        }
        /**
         * 
         * 
         */
        public final static class Integer
            extends CF.Constants.Value1
        {        
            protected Integer(int value){
                super(CF.Constants.INTEGER,value);
            }
            protected Integer(Key key, int value){
                super(key, CF.Constants.INTEGER,value);
            }
        }
        /**
         * 
         * 
         */
        public final static class Float
            extends CF.Constants.Value1
        {        
            protected Float(int value){
                super(CF.Constants.FLOAT,value);
            }
            protected Float(Key key, int value){
                super(key, CF.Constants.FLOAT,value);
            }
        }
        /** 
         * @see CF$Constants$Long
         * @see CF$Constants$Double
         */
        public static abstract class Value2 
            extends CF.Constants.Const
        {
            public final static class Key
                extends java.lang.Object
            {
                private final long value;
                private final java.lang.String string;
                private final int hashcode;
        
                public Key(long value){
                    super();
                    this.value = value;
                    this.string = java.lang.Long.toHexString(value);
                    this.hashcode = (int)value;
                }
                public int hashCode(){
                    return this.hashcode;
                }
                public boolean equals(java.lang.Object another){
                    if (another == this)
                        return true;
                    else if (another instanceof java.lang.Number)
                        return (this.value == ((java.lang.Number)another).longValue());
                    else if (another == this.string)
                        return true;
                    else
                        return this.string.equals(another.toString());
                }
                public java.lang.String toString(){
                    return this.string;
                }
            }
        
            private int tag;
        
            private long value;
        
            protected Value2 (int tag, long value){
                this (new Key(value), tag, value);
            }
            protected Value2 (Key key, int tag, long value){
                super (key);
                this.tag = tag;
                this.value = value;
            }
        
            public int getTag() { 
                return this.tag;
            }
            public final java.lang.Number getValue(){
                switch (this.tag){
                case CF.Constants.LONG:
                    return new java.lang.Long(this.value);
                case CF.Constants.DOUBLE:
                    double value = java.lang.Double.longBitsToDouble(this.value);
                    return new java.lang.Double(value);
                default:
                    throw new Error.Bug();
                }
            }
            public void writeCF (CF.Writer dstr) 
                throws java.io.IOException
            {
                dstr.writeByte(this.tag);
                dstr.writeLong(this.value);
            }
            public java.lang.String toString(){
                syntelos.iou.chbuf strbuf = new syntelos.iou.chbuf();
                switch(this.tag){
                case CF.Constants.LONG:
                    strbuf.append(SCHEME_LONG);
                    break;
                case CF.Constants.DOUBLE:
                    strbuf.append(SCHEME_DOUBLE);
                    break;
                default:
                    throw new Error.Bug("Unrecognized tag 0x"+java.lang.Integer.toHexString(this.tag));
                }
                strbuf.append(':');
                strbuf.append(this.getValue().toString());
                return strbuf.toString();
            }
        }
        /**
         * 
         * 
         */
        public final static class Long
            extends CF.Constants.Value2
        {        
            protected Long(long value){
                super(CF.Constants.LONG,value);
            }
            protected Long(Key key, long value){
                super(key,CF.Constants.LONG,value);
            }
        }
        /**
         * 
         * 
         */
        public final static class Double
            extends CF.Constants.Value2
        {        
            protected Double(double value){
                super(CF.Constants.DOUBLE,java.lang.Double.doubleToLongBits(value));
            }
            protected Double(long value){
                super(CF.Constants.DOUBLE,value);
            }
            protected Double(Key key, long value){
                super(key,CF.Constants.DOUBLE,value);
            }
        }
        /**
         * <p> Simple value CP entries including UTF8, INTEGER, FLOAT,
         * LONG and DOUBLE are constructed in order with complex CP
         * entries that may reference them.  This structure preserves the
         * information read from the stream for resolution after the
         * stream has been read. </p>
         * 
         * <p>  </p>
         *
         */
        protected static class ReadcfTodo
            extends CF.Constants.Const
        {
            protected int this_cpx, tag; 

            protected java.lang.String value_utf8;

            protected int value_1;

            protected long value_2;

            protected ReadcfTodo(int this_cpx, int tag){
                super();
                this.this_cpx = this_cpx;
                this.tag = tag;
            }
            protected ReadcfTodo(int this_cpx, int tag, java.lang.String value){
                this(this_cpx,tag);
                this.value_utf8 = value;
            }
            protected ReadcfTodo(int this_cpx, int tag, int value){
                this(this_cpx,tag);
                this.value_1 = value;
            }
            protected ReadcfTodo(int this_cpx, int tag, long value){
                this(this_cpx,tag);
                this.value_2 = value;
            }
            protected boolean install(Constants cp){
                switch (this.tag){
                case UTF8:
                    return (null != cp.constUtf8(this.this_cpx,this.value_utf8));

                case INTEGER:
                case FLOAT:
                    return (null != cp.constValue1(this.this_cpx,this.tag,this.value_1));

                case LONG:
                case DOUBLE:
                    return (null != cp.constValue2(this.this_cpx,this.tag,this.value_2));

                default:
                    throw new Error.State(java.lang.String.valueOf(tag));
                }
            }

            public final int getTag(){
                return this.tag;
            }
            public java.lang.String toString(){
                throw new Error.Bug();
            }
        }
        /**
         * <p> Complex CP entries including CLASS, STRING, REF and
         * NAME+TYPE reference other constant pool entries.  When these
         * references point to entries not yet read from the class file
         * stream, they are unresolvable forward references.  This
         * structure preserves the information read from the stream for
         * resolution after the stream has been read. </p>
         * 
         * <p>  </p>
         *
         */
        protected final static class ReadcfRe
            extends ReadcfTodo
        {
            protected int cpx1, cpx2; 

            protected ReadcfRe(int this_cpx, int tag, int cpx1){
                this(this_cpx,tag,cpx1,0);
            }
            protected ReadcfRe(int this_cpx, int tag, int cpx1, int cpx2){
                super(this_cpx,tag);
                this.cpx1 = cpx1;
                this.cpx2 = cpx2;
            }
            protected boolean install(Constants cp){
                switch (this.tag){
                case CLASS:
                    int class_name_cpx = this.cpx1;
                    return cp.constClass(this.this_cpx,class_name_cpx);

                case STRING:
                    int string_value_cpx = this.cpx1;
                    return cp.constString(this.this_cpx,string_value_cpx);

                case FIELDREF:
                case METHODREF:
                case IMETHODREF:
                    int ref_class_cpx = this.cpx1;
                    int ref_nt_cpx = this.cpx2;
                    return cp.constRef(this.this_cpx,this.tag,ref_class_cpx,ref_nt_cpx);

                case NAME_AND_TYPE:
                    int nt_name_cpx = this.cpx1;
                    int nt_type_cpx = this.cpx2;
                    return cp.constNameAndType(this.this_cpx,nt_name_cpx,nt_type_cpx);

                default:
                    throw new Error.Bug(java.lang.String.valueOf(tag));
                }
            }
        }


        /**
         * @see #add(syntelos.xb.CF$Constants$Const)
         */
        public Constants(){
            super();
        }

        public int getCount(){
            return super.size();
        }
        public CF.Constants.Const getConst(IO.Uri uri){
            switch(Scheme(uri)){
            case NIL:
                return this.constNil(uri);
            case UTF8:
                return this.constUtf8(uri);
            case INTEGER:
                return this.constInteger(uri);
            case FLOAT:
                return this.constFloat(uri);
            case LONG:
                return this.constLong(uri);
            case DOUBLE:
                return this.constDouble(uri);
            case CLASS:
                return this.constClass(uri);
            case STRING:
                return this.constString(uri);
            case FIELDREF:
                return this.constFieldRef(uri);
            case METHODREF:
                return this.constMethodRef(uri);
            case IMETHODREF:
                return this.constIMethodRef(uri);
            default:
                throw new Error.Argument(uri.toString());
            }
        }
        public int getConstIndex(IO.Uri uri){
            CF.Constants.Const cconst = this.getConst(uri);
            if (null != cconst)
                return cconst.getIndex();
            else
                throw new Error.State("Constant not found '"+uri+"'.");
        }
        /**
         * @param index Constant pool index counts from one, zero
         * returns {@link CF$Constants$Const$Nil}
         */
        public CF.Constants.Const getConst(int index){

            return (CF.Constants.Const)super.value(index);
        }
        public CF.Constants.Utf8 getConstUtf8(int index){
            return (CF.Constants.Utf8)super.value(index);
        }
        public CF.Constants.Long getConstLong(int index){
            return (CF.Constants.Long)super.value(index);
        }
        public CF.Constants.Integer getConstInteger(int index){
            return (CF.Constants.Integer)super.value(index);
        }
        public CF.Constants.Float getConstFloat(int index){
            return (CF.Constants.Float)super.value(index);
        }
        public CF.Constants.Double getConstDouble(int index){
            return (CF.Constants.Double)super.value(index);
        }
        public CF.Constants.String getConstString(int index){
            return (CF.Constants.String)super.value(index);
        }
        public CF.Constants.Class getConstClass(int index){
            return (CF.Constants.Class)super.value(index);
        }
        public CF.Constants.FieldRef getConstFieldRef(int index){
            return (CF.Constants.FieldRef)super.value(index);
        }
        public CF.Constants.MethodRef getConstMethodRef(int index){
            return (CF.Constants.MethodRef)super.value(index);
        }
        public CF.Constants.IMethodRef getConstIMethodRef(int index){
            return (CF.Constants.IMethodRef)super.value(index);
        }
        /**
         * @param ent New constant 
         * @see CF$Constants$Const#setIndex(int)}
         * @see CF$Constants$Const#NIL
         */
        public CF.Constants.Const add(CF.Constants.Const ent){
            return this.add(0,ent);
        }
        protected CF.Constants.Const add(int this_cpx, CF.Constants.Const ent){
            if (null == ent)
                throw new Error.Argument("Null entry.");
            else {
                if (0 == this.size()){
                    CF.Constants.Const nil = CF.Constants.Const.NIL;
                    super.append(nil.getKey(),nil);
                    if (ent instanceof CF.Constants.Const.Nil)
                        return nil;
                }
                //
                if (0 != this_cpx){
                    CF.Constants.Const test = (CF.Constants.Const)this.value(this_cpx);
                    if (null != test){
                        if (test instanceof ReadcfTodo){
                            int re_idx = this.replace(this_cpx,ent.getKey(),ent);
                            if (this_cpx != re_idx)
                                throw new Error.Bug("index-conflict?this_cpx="+this_cpx+"&re_idx="+re_idx);
                            else {
                                ent.setIndex(re_idx);
                                return ent;
                            }
                        }
                        else
                            throw new Error.Bug("index-conflict?this_cpx="+this_cpx+"&existing-class="+test.getClass().getName());
                    }
                    /* (else (null == this.value(cpx))
                     *  continue)
                     */
                }
                //
                int re_idx = super.append(ent.getKey(),ent);
                if (0 != this_cpx && re_idx != this_cpx)
                    throw new Error.Bug("index-conflict?this_cpx="+this_cpx+"&re_idx="+re_idx);
                else {
                    ent.setIndex(re_idx);
                    switch (ent.getTag()){
                    case LONG:
                    case DOUBLE:
                        {
                            CF.Constants.Const nil = CF.Constants.Const.NIL;
                            super.append(nil.getKey(),nil);
                        }
                        return ent;
                    default:
                        return ent;
                    }
                }
            }
        }
        protected CF.Constants.Const constNil (IO.Uri uri){
            if (SCHEME_NIL.equals(uri.getSchemeHead())){
                CF.Constants.Const nil = this.getConst(0);
                if (null == nil)
                    return this.add(0,CF.Constants.Const.NIL);
                else
                    return nil;
            }
            else
                throw new Error.Argument(uri.toString());
        }
        public CF.Constants.Utf8 constUtf8 (java.lang.String s){
            return this.constUtf8(0,s);
        }
        public CF.Constants.Utf8 constUtf8 (IO.Uri uri){
            if (SCHEME_UTF8.equals(uri.getSchemeHead()))
                return this.constUtf8(0,uri.getPath());
            else
                throw new Error.Argument(uri.toString());
        }
        protected CF.Constants.Utf8 constUtf8 (int this_cpx, java.lang.String s){
            if (null == s)
                throw new Error.Argument("null string");
            else {
                CF.Constants.Utf8.Key lookup = new CF.Constants.Utf8.Key(s);
                java.lang.Object test = super.get(lookup);
                if (test instanceof CF.Constants.Utf8)
                    return (CF.Constants.Utf8)test;
                else if (null == test){
                    CF.Constants.Utf8 re = new CF.Constants.Utf8(lookup,s);
                    this.add(this_cpx,re);
                    return re;
                }
                else
                    throw new Error.State("conflicting-types");
            }
        }
        protected boolean constClass (int this_cpx, int name_cpx){
            CF.Constants.Const name_entry = this.getConst(name_cpx);
            if (name_entry instanceof CF.Constants.Utf8){
                CF.Constants.Utf8 name = (CF.Constants.Utf8)name_entry;
                return (null != this.constClass(this_cpx,name));
            }
            return false;
        }
        public CF.Constants.Class constClass (CF.Constants.Utf8 name){
            return this.constClass(0,name);
        }
        public CF.Constants.Class constClass (IO.Uri uri){
            if (SCHEME_CLASS.equals(uri.getSchemeHead()) &&
                SCHEME_UTF8.equals(uri.getSchemeTail()))
                {
                    java.lang.String desc = uri.getPath();
                    CF.Constants.Utf8 utf8 = this.constUtf8(desc);
                    return this.constClass(utf8);
                }
            else
                throw new Error.Argument(uri.toString());
        }
        protected CF.Constants.Class constClass (int this_cpx, CF.Constants.Utf8 name){
            if (null == name)
                throw new Error.Argument("null name");
            else {
                CF.Constants.Class.Key lookup = new CF.Constants.Class.Key(name);
                java.lang.Object test = super.get(lookup);
                if (test instanceof CF.Constants.Class)
                    return (CF.Constants.Class)test;
                else if (null == test){
                    CF.Constants.Class re = new CF.Constants.Class(lookup,name);
                    this.add(this_cpx,re);
                    return re;
                }
                else
                    throw new Error.State("conflicting-types");
            }
        }
        private CF.Constants.Value1 constValue1 (int tag, int val){
            return this.constValue1(0,tag,val);
        }
        private CF.Constants.Value1 constValue1 (int cpx, int tag, int val){
            CF.Constants.Value1.Key lookup = new CF.Constants.Value1.Key(val);
            java.lang.Object test = super.get(lookup);
            if (test instanceof CF.Constants.Value1)
                return (CF.Constants.Value1)test;
            else if (null == test){
                CF.Constants.Value1 re;
                switch (tag){
                case INTEGER:
                    re = new CF.Constants.Integer(lookup,val);
                    break;
                case FLOAT:
                    re = new CF.Constants.Float(lookup,val);
                    break;
                default:
                    throw new Error.Bug();
                }
                this.add(cpx,re);
                return re;
            }
            else
                throw new Error.State("conflicting-types");
        }
        private CF.Constants.Value2 constValue2 (int tag, long val){
            return this.constValue2(0,tag,val);
        }
        private CF.Constants.Value2 constValue2 (int cpx, int tag, long val){
            CF.Constants.Value2.Key lookup = new CF.Constants.Value2.Key(val);
            java.lang.Object test = super.get(lookup);
            if (test instanceof CF.Constants.Value2)
                return (CF.Constants.Value2)test;
            else if (null == test){
                CF.Constants.Value2 re;
                switch (tag){
                case LONG:
                    re = new CF.Constants.Long(lookup,val);
                    break;
                case DOUBLE:
                    re = new CF.Constants.Double(lookup,val);
                    break;
                default:
                    throw new Error.Bug();
                }
                this.add(cpx,re);
                return re;
            }
            else
                throw new Error.State("conflicting-types");
        }
        public CF.Constants.Integer constInteger (int val){
            return (CF.Constants.Integer)this.constValue1(INTEGER, val);
        }
        public CF.Constants.Integer constInteger (IO.Uri uri){
            if (SCHEME_INTEGER.equals(uri.getSchemeHead())){
                try {
                    java.lang.String string = uri.getPath();
                    int val = java.lang.Integer.decode(string).intValue();
                    return this.constInteger(val);
                }
                catch (java.lang.NumberFormatException nfx){
                    throw new Error.Argument(nfx,uri.toString());
                }
            }
            else
                throw new Error.Argument(uri.toString());
        }
        public CF.Constants.Long constLong (long val){
            return (CF.Constants.Long)this.constValue2(LONG, val);
        }
        public CF.Constants.Long constLong (IO.Uri uri){
            if (SCHEME_LONG.equals(uri.getSchemeHead())){
                try {
                    java.lang.String string = uri.getPath();
                    long val = java.lang.Long.decode(string).intValue();
                    return this.constLong(val);
                }
                catch (java.lang.NumberFormatException nfx){
                    throw new Error.Argument(nfx,uri.toString());
                }
            }
            else
                throw new Error.Argument(uri.toString());
        }
        public CF.Constants.Float constFloat (float val){
            return (CF.Constants.Float)this.constValue1(FLOAT, java.lang.Float.floatToIntBits(val));
        }
        public CF.Constants.Float constFloat (IO.Uri uri){
            if (SCHEME_FLOAT.equals(uri.getSchemeHead())){
                try {
                    java.lang.String string = uri.getPath();
                    float val = new java.lang.Float(string).floatValue();
                    return this.constFloat(val);
                }
                catch (java.lang.NumberFormatException nfx){
                    throw new Error.Argument(nfx,uri.toString());
                }
            }
            throw new Error.Argument(uri.toString());
        }
        public CF.Constants.Double constDouble (double val){
            return (CF.Constants.Double)this.constValue2(DOUBLE, java.lang.Double.doubleToLongBits(val));
        }
        public CF.Constants.Double constDouble (IO.Uri uri){
            if (SCHEME_DOUBLE.equals(uri.getSchemeHead())){
                try {
                    java.lang.String string = uri.getPath();
                    double val = new java.lang.Double(string).doubleValue();
                    return this.constDouble(val);
                }
                catch (java.lang.NumberFormatException nfx){
                    throw new Error.Argument(nfx,uri.toString());
                }
            }
            throw new Error.Argument(uri.toString());
        }
        protected boolean constString( int this_cpx, int value_cpx){
            CF.Constants.Const entry = this.getConst(value_cpx);
            if (entry instanceof CF.Constants.Utf8){
                CF.Constants.Utf8 value = (CF.Constants.Utf8)entry;
                return (null != this.constString(this_cpx,value));
            }
            return false;
        }
        public CF.Constants.String constString (IO.Uri uri){
            if (SCHEME_STRING.equals(uri.getSchemeHead()) && 
                SCHEME_UTF8.equals(uri.getSchemeTail()))
                {
                    IO.Uri uutf8 = new IO.Uri(uri,IO.Uri.TYPE_SCHEME_1);
                    Utf8 utf8 = this.constUtf8(uutf8);
                    return this.constString(utf8);
                }
            else
                throw new Error.Argument(uri.toString());
        }
        public CF.Constants.String constString (CF.Constants.Utf8 str){
            return this.constString(0,str);
        }
        protected CF.Constants.String constString (int this_cpx, CF.Constants.Utf8 str){
            if (null == str)
                throw new Error.Argument("null utf8-string");
            else {
                CF.Constants.String.Key lookup = new CF.Constants.String.Key(str);
                java.lang.Object test = super.get(lookup);
                if (test instanceof CF.Constants.String)
                    return (CF.Constants.String)test;
                else if (null == test){
                    CF.Constants.String re = new CF.Constants.String(lookup,str);
                    this.add(this_cpx,re);
                    return re;
                }
                else
                    throw new Error.State("conflicting-types");
            }
        }
        protected boolean constNameAndType( int this_cpx, int name_cpx, int type_cpx){
            CF.Constants.Const name_entry = this.getConst(name_cpx);
            if (name_entry instanceof CF.Constants.Utf8){
                CF.Constants.Utf8 name = (CF.Constants.Utf8)name_entry;
                CF.Constants.Const type_entry = this.getConst(type_cpx);
                if (type_entry instanceof CF.Constants.Utf8){
                    CF.Constants.Utf8 type = (CF.Constants.Utf8)type_entry;
                    return (null != this.constNameAndType(this_cpx,name,type));
                }
            }
            return false;
        }
        public CF.Constants.NameAndType constNameAndType (CF.Constants.Utf8 name, CF.Constants.Utf8 type){
            return this.constNameAndType(0,name,type);
        }
        public CF.Constants.NameAndType constNameAndType (IO.Uri uri){
            java.lang.String name = uri.getQuery("name");
            java.lang.String type = uri.getQuery("type");
            if (null != name && null != type){
                CF.Constants.Utf8 const_name = this.constUtf8(new IO.Uri(name));
                CF.Constants.Utf8 const_type = this.constUtf8(new IO.Uri(type));
                return this.constNameAndType(const_name, const_type);
            }
            else
                throw new Error.Argument(uri.toString());
        }
        protected CF.Constants.NameAndType constNameAndType (int this_cpx, CF.Constants.Utf8 name, CF.Constants.Utf8 type){
            if (null == name)
                throw new Error.Argument("Null 'name'.");
            else if (null == type)
                throw new Error.Argument("Null 'type'.");
            else {
                CF.Constants.NameAndType.Key lookup = new CF.Constants.NameAndType.Key(name,type);
                java.lang.Object test = super.get(lookup);
                if (test instanceof CF.Constants.NameAndType)
                    return (CF.Constants.NameAndType)test;
                else if (null == test){
                    CF.Constants.NameAndType re = new CF.Constants.NameAndType(lookup,name,type);
                    this.add(this_cpx,re);
                    return re;
                }
                else
                    throw new Error.State("conflicting-types");
            }
        }
        private boolean constRef( int this_cpx, int tag, int class_cpx, int nt_cpx){
            CF.Constants.Const clas_entry = this.getConst(class_cpx);
            if (clas_entry instanceof CF.Constants.Class){
                CF.Constants.Class clas = (CF.Constants.Class)clas_entry;
                CF.Constants.Const namt_entry = this.getConst(nt_cpx);
                if (namt_entry instanceof CF.Constants.NameAndType){
                    CF.Constants.NameAndType namt = (CF.Constants.NameAndType)namt_entry;
                    return (null != this.constRef(this_cpx,tag,clas,namt));
                }
            }
            return false;
        }
        private CF.Constants.Ref constRef (int tag, CF.Constants.Class clas, CF.Constants.NameAndType nt){
            return this.constRef(0,tag,clas,nt);
        }
        private CF.Constants.Ref constRef (int this_cpx, int tag, CF.Constants.Class clas, CF.Constants.NameAndType nameAndType){
            if (null == clas)
                throw new Error.Argument("null class");
            else if (null == nameAndType)
                throw new Error.Argument("null name-and-type");
            else {
                CF.Constants.Ref.Key lookup = new CF.Constants.Ref.Key(clas,nameAndType);
                java.lang.Object test = super.get(lookup);
                if (test instanceof CF.Constants.Ref)
                    return (CF.Constants.Ref)test;
                else if (null == test){
                    CF.Constants.Ref re;
                    switch (tag){
                    case FIELDREF:
                        re = new CF.Constants.FieldRef(lookup,clas,nameAndType);
                        break;
                    case METHODREF:
                        re = new CF.Constants.MethodRef(lookup,clas,nameAndType);
                        break;
                    case IMETHODREF:
                        re = new CF.Constants.IMethodRef(lookup,clas,nameAndType);
                        break;
                    default:
                        throw new Error.Bug();
                    }
                    this.add(this_cpx,re);
                    return re;
                }
                else
                    throw new Error.State("conflicting-types");
            }
        }
        /**
         * @return Reference to method not in interface
         */
        public CF.Constants.MethodRef constMethodRef (CF.Constants.Class clas, CF.Constants.NameAndType nameType){
            return (CF.Constants.MethodRef)this.constRef(METHODREF, clas, nameType);
        }
        public CF.Constants.MethodRef constMethodRef (IO.Uri uri){
            if (SCHEME_METHODREF.equals(uri.getSchemeHead()) &&
                SCHEME_CLASS.equals(uri.getScheme(1)) &&
                SCHEME_UTF8.equals(uri.getSchemeTail()))
                {
                    IO.Uri uclass = new IO.Uri(uri,IO.Uri.TYPE_SCHEME_1);
                    CF.Constants.Class cclass = this.constClass(uclass);
                    CF.Constants.NameAndType name_and_type = this.constNameAndType(uri);
                    return this.constMethodRef(cclass,name_and_type);
                }
            throw new Error.Argument(uri.toString());
        }
        /**
         * @return Reference to method in interface
         */
        public CF.Constants.IMethodRef constIMethodRef (CF.Constants.Class clas, CF.Constants.NameAndType nameType){
            return (CF.Constants.IMethodRef)this.constRef(IMETHODREF, clas, nameType);
        }
        public CF.Constants.IMethodRef constIMethodRef (IO.Uri uri){
            if (SCHEME_IMETHODREF.equals(uri.getSchemeHead()) &&
                SCHEME_CLASS.equals(uri.getScheme(1)) &&
                SCHEME_UTF8.equals(uri.getSchemeTail()))
                {
                    IO.Uri uclass = new IO.Uri(uri,IO.Uri.TYPE_SCHEME_1);
                    CF.Constants.Class cclass = this.constClass(uclass);
                    CF.Constants.NameAndType name_and_type = this.constNameAndType(uri);
                    return this.constIMethodRef(cclass,name_and_type);
                }
            throw new Error.Argument(uri.toString());
        }
        public CF.Constants.FieldRef constFieldRef (CF.Constants.Class clas, CF.Constants.NameAndType nameType){
            return (CF.Constants.FieldRef)this.constRef(FIELDREF, clas, nameType);
        }
        public CF.Constants.FieldRef constFieldRef (IO.Uri uri){
            if (SCHEME_FIELDREF.equals(uri.getSchemeHead()) &&
                SCHEME_CLASS.equals(uri.getScheme(1)) &&
                SCHEME_UTF8.equals(uri.getSchemeTail()))
                {
                    IO.Uri uclass = new IO.Uri(uri,IO.Uri.TYPE_SCHEME_1);
                    CF.Constants.Class cclass = this.constClass(uclass);
                    CF.Constants.NameAndType name_and_type = this.constNameAndType(uri);
                    return this.constFieldRef(cclass,name_and_type);
                }
            throw new Error.Argument(uri.toString());
        }
        public void readCF(IO.Uri src, CF.Reader din)
            throws java.io.IOException
        {
            this.clear();
            int cp_count = din.readUnsignedShort();

            byte tag;
            /*
             * This process implements a scheme to minimize the impact
             * of forward references within the constant pool as read
             * from input, to avoid the need to put entries into the
             * constant pool (lookup table) that don't yet have their
             * keys.
             * 
             * We construct a complete set of "todos" from input, and then
             * process them into the constant pool afterwards, in the
             * second loop below, as they can find their proper lookup
             * keys.
             */
            ReadcfTodo[] readcf_todo_list = new ReadcfTodo[cp_count];
            //
            for (int cc = 1;  cc < cp_count;  cc++){
                tag = din.readByte();
                switch (tag){
                case UTF8:
                    java.lang.String utf8 = din.readUTF();
                    readcf_todo_list[cc] = new ReadcfTodo(cc,tag,utf8);
                    break;
                case INTEGER:
                case FLOAT:
                    int value1 = din.readInt();
                    readcf_todo_list[cc] = new ReadcfTodo(cc,tag,value1);
                    break;
                case LONG:
                case DOUBLE:
                    long value2 = din.readLong();
                    readcf_todo_list[cc] = new ReadcfTodo(cc,tag,value2);
                    cc += 1;
                    break;
                case CLASS:
                    int class_name_cpx = din.readUnsignedShort();
                    readcf_todo_list[cc] = new ReadcfRe(cc,tag,class_name_cpx);
                    break;
                case STRING:
                    int string_value_cpx = din.readUnsignedShort();
                    readcf_todo_list[cc] = new ReadcfRe(cc,tag,string_value_cpx);
                    break;
                case FIELDREF:
                case METHODREF:
                case IMETHODREF:
                    int ref_class_cpx = din.readUnsignedShort();
                    int ref_nt_cpx = din.readUnsignedShort();
                    readcf_todo_list[cc] = new ReadcfRe(cc,tag,ref_class_cpx,ref_nt_cpx);
                    break;
                case NAME_AND_TYPE:
                    int nt_name_cpx = din.readUnsignedShort();
                    int nt_type_cpx = din.readUnsignedShort();
                    readcf_todo_list[cc] = new ReadcfRe(cc,tag,nt_name_cpx,nt_type_cpx);
                    break;
                default:
                    throw new Error.Format("Unrecognized tag 0x"+java.lang.Integer.toHexString(tag & 0xff));
                }
            }
            /*
             * Process input into index table
             */
            ReadcfTodo tobedone;
            int done = 1;
            while (done < cp_count){
                for (int cc = 1;  cc < cp_count;  cc++){
                    tobedone = readcf_todo_list[cc];
                    if (null != tobedone){
                        if (tobedone.install(this)){
                            done += 1;
                            switch (tobedone.tag){
                            case LONG:
                            case DOUBLE:
                                done += 1;
                                break;
                            default:
                                break;
                            }
                            readcf_todo_list[cc] = null;
                        }
                        else if (null == this.getConst(cc)){
                            this.add(cc,tobedone);
                        }
                    }
                }
            }
        }

        public void writeCF (IO.Uri dst, CF.Writer dout) 
            throws java.io.IOException
        {
            CF.Constants.Const nil = CF.Constants.Const.NIL;
            int cp_count = this.getCount();
            dout.writeShort(cp_count);
            for (int cc = 1; cc < cp_count; cc++){
                CF.Constants.Const entry = this.getConst(cc);
                if (entry != null && nil != entry)
                    entry.writeCF(dout);
            }
        }
    }



    public void readCF(IO.Uri src, CF.Reader reader)
        throws java.io.IOException;

    public void writeCF(IO.Uri dst, CF.Writer writer)
        throws java.io.IOException;
}
